package cn.wizzer.app.sys.modules.services.impl;

import cn.wizzer.app.sys.modules.models.SysBankLib;
import cn.wizzer.app.sys.modules.models.SysCurrency;
import cn.wizzer.app.sys.modules.models.vo.SysBankLibVo;
import cn.wizzer.app.sys.modules.models.vo.SysBankVo;
import cn.wizzer.app.sys.modules.services.SysBankLibService;
import cn.wizzer.app.sys.modules.services.SysCurrencyService;
import cn.wizzer.framework.base.service.BaseServiceImpl;
import cn.wizzer.framework.base.service.CommonDBService;
import cn.wizzer.framework.page.Pagination;
import com.alibaba.dubbo.config.annotation.Service;
import org.apache.commons.lang3.ArrayUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.plugins.wkcache.annotation.CacheDefaults;
import org.nutz.plugins.wkcache.annotation.CacheRemoveAll;
import org.nutz.plugins.wkcache.annotation.CacheResult;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


@IocBean(args = {"refer:dao"})
@Service(interfaceClass = SysBankLibService.class)
@CacheDefaults(cacheName = "sys_bank_lib")
public class SysBankLibServiceImpl extends BaseServiceImpl<SysBankLib> implements SysBankLibService {

    public SysBankLibServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private SysCurrencyService currencyService;

    @Inject
    private CommonDBService dbService;


    @Override
    public List<SysBankVo> list() {
        // 查询国家集合(过滤默认币种、数字货币、国家为空、体验金币种)
        Cnd cnd = Cnd.where("country", "is not", null).and("digital", "=", 0)
                .and("id", "!=", "default").and("name", "!=", "USD(EXP)")
                .and("delFlag", "=", 0);
        List<SysCurrency> list = currencyService.query(cnd);
        // 转换成vo集合
        List<SysBankVo> countryList = list.stream()
                .map(currency -> {
                    SysBankVo countryVo = new SysBankVo();
                    countryVo.setLabel(currency.getCountry());
                    countryVo.setValue(currency.getId());
                    return countryVo;
                })
                .distinct()
                .collect(Collectors.toList());
        this.getBankTree(countryList);
        return countryList;
    }

    /**
     * 获得国家下的银行集合
     *
     * @param countryList
     */
    private void getBankTree(List<SysBankVo> countryList) {
        // 查询没有被禁用的银行集合
        List<SysBankLib> bankLibs = this.query(Cnd.where("disabled", "=", 0));
        // 查询国家下的银行 组装vo
        for (SysBankVo countryVo : countryList) {
            List<SysBankVo> banVos = bankLibs.stream()
                    .map(bank -> {
                        if (Strings.isNotBlank(bank.getName()) && bank.getCurrencyId().equals(countryVo.getValue())) {
                            SysBankVo bankVo = new SysBankVo();
                            bankVo.setLabel(bank.getName() + "(" + bank.getShortName() + ")");
                            bankVo.setValue(bank.getId());
                            return bankVo;
                        }
                        return null;
                    })
                    .distinct()
                    .filter(Objects::nonNull)
                    .sorted(Comparator.comparing(SysBankVo::getLabel))
                    .collect(Collectors.toList());
            countryVo.setChildren(banVos.size() == 0 ? null : banVos);
        }
    }


    @Override
    public Pagination listPage(Integer pageNumber, int pageSize, String searchKeyword, String[] searchDate) {
        // 根据收款人,银行卡号搜索
        Sql sql = Sqls.create("SELECT bl.*,c.country,c.logo as flag FROM sys_bank_lib AS bl ");
        Sql countSql = Sqls.create("select count(1) FROM sys_bank_lib AS bl ");
        String joinSql = "LEFT JOIN sys_currency AS c ON bl.currencyId = c.id $condition ";
        sql.appendSourceSql(joinSql);
        countSql.appendSourceSql(joinSql);
        Cnd cnd = Cnd.NEW();
        if (Strings.isNotBlank(searchKeyword)) {
            searchKeyword = "%" + searchKeyword + "%";
            cnd.and(Cnd.exps("bl.name", "like", searchKeyword)
                    .or("bl.shortName", "like", searchKeyword)
                    .or("c.country", "like", searchKeyword));
        }
        if (ArrayUtils.isNotEmpty(searchDate)) {
            cnd.and("opAt", ">=", Times.d2TS(Times.D(searchDate[0])));
            cnd.and("opAt", "<=", Times.d2TS(Times.D(searchDate[1])));
        }
        sql.setCondition(cnd);
        sql.appendSourceSql("order by opAt desc");
        countSql.setCondition(cnd);
        return dbService.listPage(SysBankLibVo.class, pageNumber, pageSize, sql.toString(), countSql.toString());
    }

    @Override
    public void add(SysBankLib bank) {
        bank.setOpAt(1L);
        this.insert(bank);
        this.clearCache();
    }

    @Override
    public void edit(SysBankLib bank) {
        this.update(bank);
        this.clearCache();
    }

    @Override
    @CacheRemoveAll
    public void clearCache() {

    }
}
